home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / e / OBEdit_src.lha / OBEdit.e < prev   
Encoding:
Text File  |  1999-07-06  |  16.7 KB  |  578 lines

  1. /*
  2.     Read a file (obdata.dat) manipulate records in it.
  3.  
  4.     This program is © 1999 Kay Ove Ovesen. You may spread it freely, as long as
  5.     the original archive contents is unchanged. You may include parts of the
  6.     code in your own programs without permission from the author.
  7.  
  8.     The program was written under OS 3.0 and compiled with AmigaE v3.3a.
  9.  
  10. */
  11.  
  12. MODULE 'tools/file', 'tools/exceptions'
  13.  
  14. /*    For practical reasons, some variables are defined globally */
  15.  
  16. DEF obfile, oblen, obname, verbose=0
  17.  
  18.     /* OBJECT INITIALIZATION */
  19.  
  20. OBJECT weapon
  21.     indx:CHAR            ->Internal Index number
  22.     name[20]:ARRAY        ->Offset 00
  23.     damage:CHAR            ->Offset 16
  24.     ammo1:CHAR            ->Offset 1A
  25.     ammo2:CHAR            ->Offset 1B
  26.     ammo3:CHAR            ->Offset 1C
  27.     dtype:CHAR            ->Offset 1F
  28.     accauto:CHAR        ->Offset 20
  29.     accsnap:CHAR        ->Offset 21
  30.     accaimed:CHAR        ->Offset 22
  31.     timeauto:CHAR        ->Offset 23
  32.     timesnap:CHAR        ->Offset 24
  33.     timeaimed:CHAR        ->Offset 25
  34.     ammords:CHAR        ->Offset 26
  35. ENDOBJECT
  36.  
  37. /*    END Object init */
  38.  
  39. /* OBJECT Methods */
  40.  
  41. PROC readobvalues(y) OF weapon
  42.     MidStr(self.name,obfile,y)
  43.     self.damage:=obfile[y+22]
  44.     self.ammo1:=obfile[y+26]
  45.     self.ammo2:=obfile[y+27]
  46.     self.ammo3:=obfile[y+28]
  47.     self.dtype:=obfile[y+31]
  48.     self.accauto:=obfile[y+32]
  49.     self.accsnap:=obfile[y+33]
  50.     self.accaimed:=obfile[y+34]
  51.     self.timeauto:=obfile[y+35]
  52.     self.timesnap:=obfile[y+36]
  53.     self.timeaimed:=obfile[y+37]
  54.     self.ammords:=obfile[y+38]
  55.     self.indx:=y/54
  56. ENDPROC
  57.  
  58. PROC writeobvalues(y, wep:PTR TO weapon)
  59.     obfile[y+22]:=wep.damage
  60.     obfile[y+26]:=wep.ammo1
  61.     obfile[y+27]:=wep.ammo2
  62.     obfile[y+28]:=wep.ammo3
  63.     obfile[y+31]:=wep.dtype
  64.     obfile[y+32]:=wep.accauto
  65.     obfile[y+33]:=wep.accsnap
  66.     obfile[y+34]:=wep.accaimed
  67.     obfile[y+35]:=wep.timeauto
  68.     obfile[y+36]:=wep.timesnap
  69.     obfile[y+37]:=wep.timeaimed
  70.     obfile[y+38]:=wep.ammords
  71. ENDPROC
  72.  
  73. PROC impvalues(rcd, wepname) OF weapon
  74. /*    All values are checked for valid ranges before import */
  75.  
  76.     MidStr(self.name,wepname,0)
  77.  
  78.     self.indx:=rcd[0]
  79.  
  80.     IF (rcd[2]>255) OR (rcd[2]<0)
  81.         PrintF('\tWARNING: Damage for object #\d (\s) is out of range!\n', rcd[0], wepname)
  82.         RETURN 1
  83.     ELSE
  84.         self.damage:=rcd[2]
  85.     ENDIF
  86.  
  87.     IF ((rcd[3]<>255) AND ((rcd[3]>79) OR (rcd[4]<0)))
  88.         PrintF('\tWARNING: Ammo1 for object #\d (\s) is out of range!\n', rcd[0], wepname)
  89.         RETURN 1
  90.     ELSE
  91.         self.ammo1:=rcd[3]
  92.     ENDIF
  93.  
  94.     IF ((rcd[4]<>255) AND ((rcd[4]>79) OR (rcd[4]<0)))
  95.         PrintF('\tWARNING: Ammo2 for object #\d (\s) is out of range!\n', rcd[0], wepname)
  96.         RETURN 1
  97.     ELSE
  98.         self.ammo2:=rcd[4]
  99.     ENDIF
  100.  
  101.     IF ((rcd[5]<>255) AND ((rcd[5]>79) OR (rcd[5]<0)))
  102.         PrintF('\tWARNING: Ammo3 for object #\d (\s) is out of range!\n', rcd[0], wepname)
  103.         RETURN 1
  104.     ELSE
  105.     self.ammo3:=rcd[5]
  106.     ENDIF
  107.  
  108.     IF (rcd[6]>255) OR (rcd[6]<0) OR ((rcd[6]>6) AND (rcd[6]<255))
  109.         PrintF('\tWARNING: Damagetype for object #\d (\s) is out of range!\n', rcd[0], wepname)
  110.         RETURN 1
  111.     ELSE
  112.         self.dtype:=rcd[6]
  113.     ENDIF
  114.  
  115.     IF (rcd[7]>255) OR (rcd[7]<0)
  116.         PrintF('\tWARNING: AccAuto for object #\d (\s) is out of range!\n', rcd[0], wepname)
  117.         RETURN 1
  118.     ELSE
  119.         self.accauto:=rcd[7]
  120.     ENDIF
  121.  
  122.     IF (rcd[8]>255) OR (rcd[8]<0)
  123.         PrintF('\tWARNING: AccSnap for object #\d (\s) is out of range!\n', rcd[0], wepname)
  124.         RETURN 1
  125.     ELSE
  126.         self.accsnap:=rcd[8]
  127.     ENDIF
  128.  
  129.     IF (rcd[9]>255) OR (rcd[9]<0)
  130.         PrintF('\tWARNING: AccAimed for object #\d (\s) is out of range!\n', rcd[0], wepname)
  131.         RETURN 1
  132.     ELSE
  133.         self.accaimed:=rcd[9]
  134.     ENDIF
  135.  
  136.     IF (rcd[10]>100) OR (rcd[10]<0)
  137.         PrintF('\tWARNING: TUAuto for object #\d (\s) is out of range!\n', rcd[0], wepname)
  138.         RETURN 1
  139.     ELSE
  140.         self.timeauto:=rcd[10]
  141.     ENDIF
  142.  
  143.     IF (rcd[11]>100) OR (rcd[11]<0)
  144.         PrintF('\tWARNING: TUSnap for object #\d (\s) is out of range!\n', rcd[0], wepname)
  145.         RETURN 1
  146.     ELSE
  147.         self.timesnap:=rcd[11]
  148.     ENDIF
  149.  
  150.     IF (rcd[12]>100) OR (rcd[12]<0)
  151.         PrintF('\tWARNING: TUAimed for object #\d (\s) is out of range!\n', rcd[0], wepname) 
  152.         RETURN 1
  153.     ELSE
  154.         self.timeaimed:=rcd[12]
  155.     ENDIF
  156.  
  157.     IF (rcd[13]>255) OR (rcd[13]<0)
  158.         PrintF('\nWARNING: AmmoRds for object #\d (\s) is out of range!\n', rcd[0], wepname)
  159.         RETURN 1
  160.     ELSE
  161.         self.ammords:=rcd[13]
  162.     ENDIF
  163. ENDPROC
  164.  
  165. PROC printobvalues(wep:PTR TO weapon)
  166.     PrintF('\nIndex:\t\t\d', wep.indx)
  167.     PrintF('\nName:\t\t\s', wep.name)
  168.     PrintF('\nDamage:\t\t\d', wep.damage)
  169.     PrintF('\nDmgType:\t\d', wep.dtype)
  170.     PrintF('\nRounds:\t\t\d', wep.ammords)
  171.     PrintF('\nAmmo 1:\t\t\d', wep.ammo1)
  172.     PrintF('\nAmmo 2:\t\t\d', wep.ammo2)
  173.     PrintF('\nAmmo 3:\t\t\d', wep.ammo3)
  174.     PrintF('\nAcc. Auto:\t\d', wep.accauto)
  175.     PrintF('\nAcc. Snap:\t\d', wep.accsnap)
  176.     PrintF('\nAcc. Aimed:\t\d', wep.accaimed)
  177.     PrintF('\nTU Auto:\t\d', wep.timeauto)
  178.     PrintF('\nTU Snap:\t\d', wep.timesnap)
  179.     PrintF('\nTU Aimed:\t\d', wep.timeaimed)
  180.     PrintF('\n\n')
  181. ENDPROC
  182.  
  183. /*    END Object methods */
  184.  
  185. PROC main() HANDLE
  186.     DEF templ, rdargs, y, args=NIL:PTR TO LONG
  187.     DEF wep:PTR TO weapon
  188.     templ:='FILE/M,OPT2/K,OPT3/K'
  189.     rdargs:=ReadArgs(templ,{args},NIL)
  190.  
  191.     PrintF('\n\t***   UFO Weapons editor v1.2   ***\n')
  192.  
  193.     IF args[0]=NIL
  194.         PrintF('\nUsage: OBEdit <FILENAME> <RECORD>')
  195.         PrintF('\nWhere <FILENAME> is file to scan and <RECORD> is #record to display.\n')
  196.         PrintF('If <RECORD> is ommitted or out of range, the program will list all records in file.\n')
  197.         PrintF('If <RECORD> is "all" then the program will list ALL objects in the file.\n\n')
  198.         PrintF('Use "export(r)ff" <FILENAME> to make an RFF 1.1-compatible database file.\n')
  199.         PrintF('Use "export(c)sv" <FILENAME> to make an ASCII-standard Comma-separated database file\n')
  200.         PrintF('Use "export(t)sv" <FILENAME> to make an ASCII-standard Tab-separated database\n')
  201.         PrintF('file with headers. (Compatible with most database programs and spreadsheets.)\n')
  202.         PrintF('Use "(i)mport" <FILENAME> to import a tab- or comma-separated ASCII file.\n')
  203.         PrintF('Use "ex" for a short list of examples.\n')
  204.         RETURN
  205.     ENDIF
  206.  
  207.     IF StrCmp(LowerStr(args[0]),'ex') THEN printexamples()
  208.  
  209.     obfile,oblen:=readfile(args[0])
  210.     PrintF('File: \s', args[0])
  211.     PrintF('\nSize: \d bytes.',oblen)
  212.     IF oblen=4320
  213.         PrintF('\nFile seems to be of correct lenght.\n')
  214.         obname:=args[0]
  215.     ELSE
  216.         PrintF(' - File is not of correct lenght for OBDATA.DAT.\n')
  217.         PrintF('Examining...')
  218.         IF StrCmp(LowerStr(args[1]),'all') OR StrCmp(args[1],'a') THEN verbose:=1
  219.         checkformat(args[0], 0)
  220.         RETURN
  221.     ENDIF
  222.  
  223.     IF StrCmp(LowerStr(args[1]),'exportcsv') OR StrCmp(args[1],'csv') OR StrCmp(args[1],'c')
  224.         IF (StrCmp(LowerStr(args[3]),'verbose') OR StrCmp(LowerStr(args[3]),'v')) THEN verbose:=1
  225.         writecsv(args[2], LowerStr(args[3]))
  226.         RETURN
  227.     ENDIF
  228.  
  229.     IF StrCmp(LowerStr(args[1]),'exporttsv') OR StrCmp(args[1],'tsv') OR StrCmp(args[1],'t')
  230.         IF (StrCmp(LowerStr(args[3]),'verbose') OR StrCmp(LowerStr(args[3]),'v')) THEN verbose:=1
  231.         writerff(args[2], LowerStr(args[3]), 0)
  232.         RETURN
  233.     ENDIF
  234.  
  235.     IF StrCmp(LowerStr(args[1]),'exportrff') OR StrCmp(args[1], 'rff') OR StrCmp(args[1],'r') 
  236.         IF (StrCmp(LowerStr(args[3]),'verbose') OR StrCmp(LowerStr(args[3]),'v')) THEN verbose:=1
  237.         writerff(args[2], LowerStr(args[3]), 1)
  238.         RETURN
  239.     ENDIF
  240.  
  241.     IF StrCmp(LowerStr(args[1]),'import') OR StrCmp(args[1], 'i') OR StrCmp(args[1], 'imp')
  242.         IF (StrCmp(LowerStr(args[3]),'verbose') OR StrCmp(LowerStr(args[3]),'v')) THEN verbose:=1
  243.         checkformat(args[2], 1)
  244.         RETURN
  245.     ENDIF
  246.  
  247.     IF StrCmp(LowerStr(args[1]),'all') OR StrCmp(args[1], 'a')
  248.         FOR y:=0 TO (oblen-54) STEP 54
  249.             NEW wep
  250.             wep.readobvalues(y)
  251.             printobvalues(wep)
  252.             END wep
  253.             IF CtrlC() THEN CleanUp()
  254.         ENDFOR
  255.         RETURN
  256.     ENDIF
  257.  
  258.     y:=(Val(args[1])*54)
  259.     IF y>(oblen-54)
  260.         PrintF('\nERROR: Record \d does not exist in \s!\n', Val(args[1]), args[0])
  261.         listrecords()
  262.         RETURN
  263.     ENDIF
  264.     
  265.     IF args[1]=NIL
  266.         listrecords()
  267.         RETURN
  268.     ENDIF
  269.  
  270.     NEW wep
  271.     wep.readobvalues(y)
  272.     printobvalues(wep)
  273.     END wep
  274.  
  275. EXCEPT
  276.     report_exception()
  277. ENDPROC
  278.  
  279. PROC listrecords() ->If no record number is given, this will simply list all records in the file.
  280.     DEF y
  281.     DEF navn
  282.  
  283.     PrintF('\nIndex:\tName:\n---------------------------\n')
  284.     FOR y:=0 TO (oblen-54) STEP 54
  285.         IF CtrlC() THEN CleanUp()
  286.         navn:=obfile+y
  287.         IF (y/54)<10
  288.             PrintF('0')
  289.         ENDIF
  290.         ->hexnumber:=(y/54)
  291.         ->hexnumber:=Val($hexnumber)
  292.         PrintF('\d\t\s\n', y/54, navn)
  293.     ENDFOR
  294. ENDPROC
  295.  
  296. PROC writecsv(csvfile, all)
  297.     DEF wep:PTR TO weapon, y
  298.     DEF tempstring[60]:STRING
  299.     DEF em[4000]:STRING
  300.     StrCopy(em, 'Index,Name,Damage,Ammo1,Ammo2,Ammo3,DmgType,Accauto,Accsnap,Accaimed,TUAuto,TUSnap,TUAimed,Rounds\n')
  301.     FOR y:=0 TO (IF StrCmp(all, 'all') THEN oblen-54 ELSE 2646) STEP 54
  302.         IF CtrlC() THEN CleanUp()
  303.         NEW wep
  304.         wep.readobvalues(y)
  305.         StringF(tempstring,'\d,\s,\d,\d,\d,\d,\d,\d,\d,\d,\d,\d,\d,\d\n', (y/54),wep.name,wep.damage,wep.ammo1,wep.ammo2,wep.ammo3,wep.dtype,wep.accauto,wep.accsnap,wep.accaimed,wep.timeauto,wep.timesnap,wep.timeaimed,wep.ammords)
  306.         IF (verbose<>0) THEN PrintF('Found weapon "\s" at index #\d.\n', wep.name, y/54)
  307.         END wep
  308.         StrAdd(em,tempstring)
  309.     ENDFOR
  310.     StrAdd(em, '\0')
  311.     writefile(csvfile,em,StrLen(em))
  312.     PrintF('\nWrote CSV-file "\s".\n\n', csvfile)
  313.     CleanUp()
  314. ENDPROC
  315.  
  316. PROC writerff(rffile, all, hdr)
  317.     DEF wep:PTR TO weapon, y
  318.     DEF tempstring[60]:STRING ->rffhdr[550]:STRING
  319.     DEF em[5000]:STRING
  320.  
  321. /*    Creating RFF Field Names */
  322.  
  323.     StrCopy(em, 'Index\tName\tDamage\tAmmo1\tAmmo2\tAmmo3\tDmgType\tAccauto\tAccsnap\tAccaimed\tTUAuto\tTUSnap\tTUAimed\tRounds\n')
  324.  
  325. /* Creating an RFF header if hdr is '1' (defined by the 'exporttsv' argument) */
  326.     IF (hdr=1)
  327.         IF FileLength('s:OBEdit.hdr')>-1    ->Check for a custom RFF header file and load this if possible.
  328.             StrAdd(em, readfile('s:OBEdit.hdr', 0))
  329.             PrintF('\nUsing custom RFF header from S:OBEdit.hdr\n')
  330.         ELSE
  331.             /* If no custom RFF header is found, default values are used. */
  332.             PrintF('\nS:OBEdit.hdr not found, using built-in default.\n')
  333.             StrAdd(em, '@RFF=1.1,TYPE=form\tFTYP=text,NAME=Index,OFFS=0,SIZE=3,NEXT=tab\tFTYP=text,NAME=Name,OFFS=1,SIZE=22,NEXT=nl\tFTYP=cycle,CENT=0,CENT=1,CENT=2,CENT=3,CENT=4,CENT=5,CENT=6,CENT=255,NAME=DmgType,OFFS=6,SIZE=6,NEXT=tab\tNAME=Damage,OFFS=2,SIZE=3,NEXT=tab\tNAME=Rounds,OFFS=13,SIZE=3,NEXT=nl\tNAME=Ammo1,OFFS=3,SIZE=3,NEXT=tab\tNAME=Ammo2,OFFS=4,SIZE=3,NEXT=tab\tNAME=Ammo3,OFFS=5,SIZE=3,NEXT=nl\tNAME=Accauto,OFFS=7,SIZE=3,NEXT=tab\tNAME=Accsnap,OFFS=8,SIZE=3,NEXT=tab\tNAME=Accaimed,OFFS=9,SIZE=3,NEXT=nl\tNAME=TUAuto,OFFS=10,SIZE=3,NEXT=tab\tNAME=TUSnap,OFFS=11,SIZE=3,NEXT=tab\tNAME=TUAimed,OFFS=12,SIZE=3,NEXT=para\n')
  334.         ENDIF
  335.     ENDIF
  336.  
  337. /*    Reading values from .dat file in memory and create an RFF file. */
  338.  
  339.     FOR y:=0 TO (IF StrCmp(all, 'all') THEN oblen-54 ELSE 2646) STEP 54
  340.         IF CtrlC() THEN CleanUp()
  341.         NEW wep
  342.         wep.readobvalues(y)
  343.         StringF(tempstring,'\d\t\s\t\d\t\d\t\d\t\d\t\d\t\d\t\d\t\d\t\d\t\d\t\d\t\d\n', (y/54),wep.name,wep.damage,wep.ammo1,wep.ammo2,wep.ammo3,wep.dtype,wep.accauto,wep.accsnap,wep.accaimed,wep.timeauto,wep.timesnap,wep.timeaimed,wep.ammords)
  344.         IF (verbose<>0) THEN PrintF('Found object "\s" at index #\d.\n', wep.name, y/54)
  345.         END wep
  346.         StrAdd(em,tempstring)
  347.     ENDFOR
  348.     StrAdd(em, '\0') -> Making sure the file is null-terminated
  349.  
  350.     writefile(rffile,em,StrLen(em))
  351.     IF hdr=1 THEN PrintF('\nWrote RFF-file "\s".\n\n', rffile) ELSE PrintF('\nWrote TSV-file "\s".\n\n', rffile)
  352.     CleanUp()
  353. ENDPROC
  354.  
  355. PROC checkformat(infile, imp)
  356.     DEF fhandle, firstline[30]:STRING
  357.     
  358.     IF fhandle:=Open(infile, OLDFILE)
  359.         Fgets(fhandle,firstline,30)
  360.         Close(fhandle)
  361.     ELSE
  362.         PrintF('\nCould not open file "\s".',infile)
  363.         RETURN
  364.     ENDIF
  365.  
  366.     IF (InStr(firstline, ',')<>-1)
  367.         PrintF('\nFile "\s" is CSV-ADCH format.\n', infile)
  368.         IF imp=1 THEN importcsv(infile) ELSE testdata(',')
  369.     ELSEIF (InStr(firstline,'    ')<>-1)
  370.         PrintF('\nFile "\s" is TSV-ADTH/RFF-DB format.\n', infile)
  371.         IF imp=1 THEN importrff(infile) ELSE testdata('    ')
  372.     ELSE
  373.         PrintF('\nABORTED: File "\s" has an unknown format.\n', infile)
  374.     ENDIF
  375. ENDPROC
  376.  
  377. PROC importrff(infile)
  378.     DEF rff, len
  379.     DEF start=0, end
  380.     rff, len:=readfile(infile)
  381.  
  382. /*    Skip to the first line after the RFF header.*/
  383.  
  384.     IF InStr(rff, '@')<>-1
  385.         start:=InStr(rff, '\n', InStr(rff, '@', start))+1
  386.     ELSE
  387.         start:=InStr(rff, '\n', start)+1
  388.     ENDIF
  389.  
  390.     REPEAT
  391.         end:=InStr(rff, '\n', start)
  392.         IF end<>-1 THEN rff[end]:=NIL
  393.         procline(rff+start, '    ')
  394.         start:=end+1
  395.     UNTIL (start>=len) OR (end=-1)
  396.  
  397.     writefile(obname, obfile, oblen)
  398.     PrintF('\nSuccessfully imported RFF file to "\s".\n', obname)
  399.     RETURN
  400. ENDPROC
  401.  
  402. PROC importcsv(infile)
  403.     DEF csv, len
  404.     DEF start=0, end
  405.     csv,len:=readfile(infile)
  406.  
  407. /*    Skip the first line containing the headers.*/
  408.  
  409.     start:=InStr(csv, '\n',start)+1
  410.  
  411.     REPEAT
  412.         end:=InStr(csv, '\n', start)
  413.         IF end<>-1 THEN csv[end]:=NIL
  414.         procline(csv+start, ',')
  415.         start:=end+1
  416.     UNTIL (start>=len) OR (end=-1)
  417.  
  418.     writefile(obname, obfile, oblen)
  419.     PrintF('\nSuccessfully imported CSV file to "\s".\n', obname)
  420.  
  421.     RETURN
  422. ENDPROC
  423.  
  424. PROC procline(line, delim)
  425.     DEF start=0, end, s, i=0
  426.     DEF rcd[14]:STRING, errline[76]:STRING, wepname[20]:STRING
  427.     DEF wep:PTR TO weapon
  428.  
  429.     IF StrLen(line)<20 THEN RETURN
  430.     StrCopy(errline, line)
  431.     REPEAT
  432.         end:=InStr(line,delim,start)
  433.         IF end<>-1 THEN line[end]:=NIL
  434.         s:=line+start
  435.         IF ((Val(s)>255) OR (Val(s)<0)) AND (i<>0)
  436.             PrintF('\tSKIPPED: "\s" - Value \d out of range (\d)!\n', errline, i+1, Val(s))
  437.             RETURN
  438.         ELSEIF ((Val(s)>79) OR (Val(s)<0)) AND (i=0)
  439.             PrintF('\tSKIPPED: "\s" - Invalid object index "\d"!\n', errline, Val(s))
  440.             RETURN
  441.         ELSE
  442.             rcd[i]:=Val(s)
  443.         ENDIF
  444.         IF(i=1) THEN StrCopy(wepname, s)
  445.         INC i
  446.         start:=end+1
  447.     UNTIL end=-1
  448.  
  449.     IF i<>14 THEN RETURN -> Check that the line contained exactly 14 values.
  450.  
  451.     NEW wep
  452.         IF    (wep.impvalues(rcd, wepname)<>1)
  453.             writeobvalues(rcd[0]*54, wep)
  454.             IF (verbose<>0) THEN PrintF('Imported object "\s" at index #\d.\n', wepname, rcd[0])
  455.         ELSE
  456.             PrintF('\tSkipped object #\d!\n', rcd[0])
  457.         ENDIF
  458.     END wep
  459.  
  460. ENDPROC
  461.  
  462. PROC printexamples() -> Print some examples of usage.
  463.     PrintF('\nAbbrevations:\n')
  464.     PrintF('\tI - Import\n')
  465.     PrintF('\tC - ExportCSV\n')
  466.     PrintF('\tT - ExportTSV\n')
  467.     PrintF('\tR - ExportRFF\n')
  468.     PrintF('\tV - Verbose\n')
  469.     PrintF('\nExamples:\n\n')
  470.     PrintF('\tOBEdit obdata.dat\n\n')
  471.     PrintF('Print a list of objects found in file "obdata.dat".\n\n')
  472.     PrintF('\tOBEdit obdata.dat 12\n\n')
  473.     PrintF('Print details about object #12 in "obdata.dat".\n\n')
  474.     PrintF('\tOBEdit obdata.dat all\n\n')
  475.     PrintF('Prints detail about ALL objects in "obdata.dat".\n\n')
  476.     PrintF('\tOBEdit obdata.dat exportcsv data.csv\n\n')
  477.     PrintF('Export data in "obdata.dat" to a comma-separated ASCII file "data.csv".\n\n')
  478.     PrintF('\tOBEdit obdata.dat exporttsv data.tsv\n\n')
  479.     PrintF('Export data in "obdata.dat" to a tab-separated ASCII file "data.tsv".\n\n')
  480.     PrintF('\tOBEdit obdata.dat exportrff data.db\n\n')
  481.     PrintF('Export data in "obdata.dat" to a tab-separated RFF file "data.db".\n\n')
  482.     PrintF('\tOBEdit obdata.dat import data.whatever\n\n')
  483.     PrintF('Import data from file "data.whatever" (either tab- or comma-separated) to "obdata.dat".\n')
  484.     CleanUp()
  485. ENDPROC
  486.  
  487. PROC testdata(delim)    /* Examine a CSV/TSV/RFF file */
  488.     DEF wep:PTR TO weapon, lstart=0,lend,start=0,end,i, records=0, errors=0, lines=0
  489.     DEF rcd[14]:STRING, line[76]:STRING, errline[76]:STRING, wepname[20]:STRING, s
  490.  
  491. /* Skip line 1 */
  492.     lstart:=InStr(obfile, '\n', lstart)+1
  493.     INC lines
  494. /* Skip RFF header if found */
  495.     IF InStr(obfile,'@',lstart)<>-1
  496.         lstart:=InStr(obfile,'\n',lstart)+1
  497.         INC lines
  498.     ENDIF
  499.     lend:=InStr(obfile,'\n',lstart)
  500.  
  501. /* Start reading */
  502.  
  503.     PrintF('\n')
  504.     IF verbose=0 THEN PrintF('Line\tIndex\tName\n------------------------\n')
  505.  
  506.     REPEAT
  507.         IF CtrlC() THEN CleanUp()
  508.         i:=0
  509.         start:=0
  510.         MidStr(line,obfile,lstart,lend-lstart)
  511.         StrCopy(errline, line)
  512.         INC lines
  513.         IF StrLen(line)>20
  514.  
  515.             REPEAT
  516.                 IF CtrlC() THEN CleanUp()
  517.                 end:=InStr(line,delim,start)
  518.                 IF end<>-1 THEN line[end]:=NIL
  519.                 s:=line+start
  520.                 IF(i=1) THEN StrCopy(wepname, s)
  521.                 IF ((Val(s)>255) OR (Val(s)<0)) AND (i<>0)
  522.                     PrintF('\tWarning: Value \d out of range (\d)!\n', i+1, Val(s))
  523.                     PrintF('Line \d: \s\n\n', lines, errline)
  524.                     INC errors
  525.                     JUMP endline
  526.                 ELSEIF ((Val(s)>79) OR (Val(s)<0)) AND (i=0)
  527.                     PrintF('\tWARNING: Invalid object index "\d"!\n', Val(s))
  528.                     PrintF('Line \d: \s\n\n', lines, errline)
  529.                     INC errors
  530.                     JUMP endline
  531.                 ELSE
  532.                     rcd[i]:=Val(s)
  533.                 ENDIF
  534.                 INC i
  535.                 start:=end+1
  536.  
  537.             UNTIL end=-1
  538.             IF i<>14
  539.                 PrintF('\tWARNING: Line \d contains incomplete or superfluous data!\n', lines)
  540.                 PrintF('Line \d: \s\n\n', lines, errline)
  541.                 INC errors
  542.                 JUMP endline
  543.             ELSE
  544.                 NEW wep
  545.                 IF    (wep.impvalues(rcd, wepname)<>1)
  546.                     IF verbose=1
  547.                         PrintF('Line \d: \s', lines, errline)
  548.                         printobvalues(wep)
  549.                     /* If Verbose is not checked, print a standard list of objects in file. */
  550.                     ELSEIF verbose=0
  551.                         PrintF('\d\t\d\t\s\n',lines,wep.indx,wep.name)
  552.                     ENDIF
  553.                     INC records
  554.                 ELSE
  555.                     PrintF('Line \d: \s\n', lines, errline)
  556.                     PrintF('\n')
  557.                     INC errors
  558.                 ENDIF
  559.                 END wep
  560.             ENDIF
  561.  
  562.         ENDIF
  563.             endline:
  564.             lstart:=lend+1
  565.             lend:=InStr(obfile,'\n',lstart)
  566.     UNTIL lend=-1
  567.  
  568. /* Print Summary */
  569.     PrintF('\n\tSUMMARY:\n')
  570.     PrintF('-------------------------\n')
  571.     PrintF('File lenght (lines):   \d\n', lines-3)
  572.     PrintF('Valid objects found:   \d\n', records)
  573.     PrintF('Invalid objects found: \d\n', errors)
  574.  
  575. ENDPROC
  576.  
  577. ver: CHAR 0,'$VER: OBEdit 1.2 (05.07.99) By Kay Ove Ovesen <ai97koo@stud.hib.no>',0
  578.